package top.hcode.hoj.service.admin;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.sagacity.sqltoy.model.MapKit;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import top.hcode.hoj.common.LazyDao;
import top.hcode.hoj.dao.CollQuestionDao;
import top.hcode.hoj.dao.CollQuestionOptionDao;
import top.hcode.hoj.dao.CollUserAnswerDao;
import top.hcode.hoj.dao.CollUserStatDao;
import top.hcode.hoj.dao.collect.ItechCollDao;
import top.hcode.hoj.dao.org.OrgDao;
import top.hcode.hoj.dao.org.OrgUserDao;
import top.hcode.hoj.manager.coll.ItechCollQuestionManager;
import top.hcode.hoj.pojo.dto.QuerySampleDTO;
import top.hcode.hoj.pojo.dto.coll.CollQuestionAnswerDTO;
import top.hcode.hoj.pojo.dto.coll.CollQuestionWithUserAnswerVO;
import top.hcode.hoj.pojo.dto.coll.QueryCollStudentSolutionDetailDTO;
import top.hcode.hoj.pojo.dto.coll.QueryNextSubjectiveQuestionToJudgeDTO;
import top.hcode.hoj.pojo.entity.CollUserStat;
import top.hcode.hoj.pojo.entity.coll.CollQuestion;
import top.hcode.hoj.pojo.entity.coll.CollQuestionOption;
import top.hcode.hoj.pojo.entity.coll.CollUserAnswer;
import top.hcode.hoj.pojo.entity.coll.ItechCollection;
import top.hcode.hoj.pojo.entity.org.ClassHasUser;
import top.hcode.hoj.pojo.vo.coll.CollQuestionJudgeRecordVO;
import top.hcode.hoj.pojo.vo.coll.CollSubjectiveQuestionToJudgeVO;
import top.hcode.hoj.pojo.vo.coll.CollUserSolutionDetailVO;
import top.hcode.hoj.service.UserAuthService;
import top.hcode.hoj.utils.Constants;
import top.hcode.hoj.utils.ConvertUtil;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author orangej
 * @since 2025-02-09
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AdminCollUserAnswerService {
    private final ItechCollDao collDao;
    private final CollUserAnswerDao userAnswerDao;
    private final CollQuestionDao questionDao;
    private final CollQuestionOptionDao questionOptionDao;
    private final CollUserStatDao userStatDao;
    private final UserAuthService userAuthService;
    private final OrgUserDao orgUserDao;
    private final OrgDao orgDao;
    private final LazyDao dao;

    private final ItechCollQuestionManager questionManager;

    public IPage<CollUserAnswer> getCollUserAnswerList(QuerySampleDTO querySampleDTO) {
        IPage<CollUserAnswer> pager = new Page<>(querySampleDTO.getCurrentPage(), querySampleDTO.getLimit());

        QueryWrapper<CollUserAnswer> query = new QueryWrapper<>();
        if (Strings.isNotBlank(querySampleDTO.getKeyword())) {
            query.like("title", querySampleDTO.getKeyword());
        }
        userAnswerDao.page(pager, query);
        return pager;
    }

    public CollUserAnswer getCollUserAnswer(Long id) {
        return userAnswerDao.getById(id);
    }

    public CollUserAnswer saveCollUserAnswer(CollUserAnswer userAnswer) {
        userAnswerDao.saveOrUpdate(userAnswer);
        return userAnswer;
    }

    public void deleteCollUserAnswer(Long id) {
        userAnswerDao.removeById(id);
    }

    public CollSubjectiveQuestionToJudgeVO getNextSubjectiveQuestionToJudge(String teacher, QueryNextSubjectiveQuestionToJudgeDTO form) {
        // 主观题id列表
        List<String> questionIdList = questionDao.querySubjectiveQuestionIdList(form.getCollId());

        // 查询教师有权限的班级id列表
        List<String> schoolIdList = userAuthService.getSchoolIdList();
        Map<String, Object> params = MapKit.startOf("schoolIdList", schoolIdList)
                .of("teacher", teacher)
                .of("classId", form.getClassId())
                .of("gradeId", form.getGradeId())
                .endOf("campusId", form.getSchoolId());
        List<String> classIdList = dao.selectList(String.class, "queryClassId", params);

        CollSubjectiveQuestionToJudgeVO result = new CollSubjectiveQuestionToJudgeVO();

        // 查询待评数量
        List<NutMap> numList = dao.selectList(NutMap.class, "querySubjectiveQuestionJudgeCount",
                MapKit.startOf("questionIdList", questionIdList).endOf("classIdList", classIdList));
        if (Lang.isEmpty(numList)) {
            return result;
        }
        int totalCount = numList.stream().mapToInt(it -> it.getInt("num")).sum();
        int judgedCount = numList.stream().filter(it -> it.getInt("judgeState") == 2)
                .mapToInt(it -> it.getInt("num")).sum();
        result.setJudgedCount(judgedCount);
        result.setTotalCount(totalCount);

        if (judgedCount >= totalCount) {
            // 已评完
            if (form.getUserId() == null) {
                // 未指定userId，指定后可以忽略评价状态，修改评分
                return result;
            }
        }

        // 查询下一个待评主观题
        CollUserAnswer userAnswer = userAnswerDao.getNextToJudge(teacher, form.getUserId(),
                form.getCurrUserAnswerId(), form.getAction(),
                questionIdList, classIdList);
        if (userAnswer == null) {
            return result;
        }

        result.setUserId(userAnswer.getUserId());
        result.setClassId(userAnswer.getClassId());
        result.setQuestionId(userAnswer.getQuestionId());
        result.setUserAnswerId(userAnswer.getId());
        result.setUserAnswer(userAnswer.getAnswer());
        result.setUserScore(userAnswer.getScore());

        CollQuestion question = questionDao.getById(userAnswer.getQuestionId());
        result.setQuestionTitle(question.getTitle());
        result.setQuestionScore(question.getScore());
        result.setQuestionOrder(question.getSortOrder());
        result.setUserName(orgUserDao.getRealNameByUid(userAnswer.getUserId()));
        result.setClassName(orgDao.getOrgNameById(userAnswer.getClassId()));

        result.setJudgeRecordList(dao.selectList(CollQuestionJudgeRecordVO.class,
                "queryCollQuestionJudgeRecordVO", MapKit.map("userAnswerId", userAnswer.getId())));

        return result;
    }

    /**
     * 统计主观题各个 judgeState 的数量
     *
     * @param collId      活动id
     * @param classIdList 班级id列表
     * @return [{judgeState, num}]
     */
    public List<NutMap> querySubjectiveQuestionJudgeCount(String collId, List<String> classIdList) {
        if (Lang.isEmpty(classIdList)) {
            return new LinkedList<>();
        }

        // 主观题id列表
        List<String> questionIdList = questionDao.querySubjectiveQuestionIdList(collId);

        if (Lang.isEmpty(questionIdList)) {
            // 无主观题，返回空列表
            return new LinkedList<>();
        }

        Map<String, Object> params = MapKit.startOf("questionIdList", questionIdList).endOf("classIdList", classIdList);

        // 统计各个judge状态的数量
        return dao.selectList(NutMap.class, "querySubjectiveQuestionJudgeCount", params);
    }

    public CollUserSolutionDetailVO getCollStudentSolutionDetail(QueryCollStudentSolutionDetailDTO form) {
        CollUserSolutionDetailVO result = new CollUserSolutionDetailVO();
        String userId = form.getUserId();
        CollUserStat userStat = userStatDao.getByUserIdAndCollId(userId, Strings.sNull(form.getCollId(), Constants.DEFAULT_COLL_ID));
        if (userStat == null) {
            return result;
        }

        Lang.copyProperties(userStat, result);


        return result;
    }

    // 返回所有题目列表，包含了正确答案和用户答案
    public List<CollQuestionWithUserAnswerVO> queryCollQuestionWithUserAnswerList(String userId, String collId) {
        // 题目列表
        List<CollQuestion> questionList = questionDao.queryByCollId(collId);

        // 题目正确答案
        List<String> questionIdList = questionList.stream().map(CollQuestion::getId).collect(Collectors.toList());
        Map<String, String> answerMap = questionDao.queryQuestionAnswerMap(questionIdList);

        List<CollUserAnswer> userAnswerList = userAnswerDao.queryByUserIdAndCollId(userId, collId);
        return questionList.stream().map(question -> {
            // 题目信息
            CollQuestionWithUserAnswerVO dto = new CollQuestionWithUserAnswerVO();
            Lang.copyProperties(ConvertUtil.toQuestionVO(question), dto);

            dto.setCollId(collId);
            dto.setQuestionAnswer(answerMap.get(question.getId()));
            dto.setUserId(userId);

            // 用户答案
            userAnswerList.stream().filter(userAnswer -> userAnswer.getQuestionId().equals(question.getId()))
                    .findFirst().ifPresent(userAnswer -> {
                        dto.setUserAnswer(userAnswer.getAnswer());
                        dto.setUserScore(userAnswer.getScore());
                        dto.setJudgeState(userAnswer.getJudgeState());
                    });

            return dto;
        }).collect(Collectors.toList());
    }

    @Transactional
    public void mockAnswers(String collId, Integer count) {
        if (count == null || count <= 0) {
            count = 10;
        }

        ItechCollection coll = collDao.getById(collId);
        if (coll == null) {
            throw new IllegalArgumentException("未知的活动 : " + collId);
        }

        List<ClassHasUser> classHasUserList = dao.selectList(ClassHasUser.class, "select * from class_has_user\n" +
                        "where org_id in \n" +
                        "      (select distinct id from org_class where find_in_set(school_id, ?) != 0 and find_in_set(grade_num, ?) != 0)\n" +
                        "and user_id not in \n" +
                        "      (select distinct user_id from coll_user_stat where coll_id = ?) " +
                        "and user_type = 0 limit " + count,
                coll.getSchoolList(), coll.getGradeList(), coll.getId());

        List<CollQuestion> questionList = questionDao.queryByCollId(collId);
        List<CollQuestionOption> questionOptionList = questionOptionDao.queryOptionByCollId(collId);

        for (ClassHasUser classHasUser : classHasUserList) {
            questionManager.startAnswer(classHasUser.getUserId(), collId);
        }

        for (ClassHasUser classHasUser : classHasUserList) {
            questionManager.startAnswer(classHasUser.getUserId(), collId);

            List<CollQuestionAnswerDTO> answerList = new LinkedList<>();
            for (CollQuestion question : questionList) {
                CollQuestionAnswerDTO answerDTO = new CollQuestionAnswerDTO();
                answerDTO.setQuestionId(question.getId());

                if (question.getQuestionType() == 1) {
                    // 随机选一个答案

                    String answer = questionOptionList.stream().filter(o -> o.getQuestionId().equals(question.getId()))
                            .filter(o -> o.getSortOrder().equals(RandomUtil.randomInt(1, 5)))
                            .map(CollQuestionOption::getId)
                            .findFirst()
                            .orElse("no");
                    answerDTO.setAnswer(answer);
                } else {
                    answerDTO.setAnswer(RandomUtil.randomString(32));
                }

                answerList.add(answerDTO);
            }

            questionManager.submitAnswer(classHasUser.getUserId(), collId, answerList);
        }
    }

}
